package com.yc.services;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yc.bean.Diary;
import com.yc.bean.User;
import com.yc.config.AiConfig;
import com.yc.config.DailyAnalysisProperties;
import com.yc.config.PersistentMemoryStore;
import com.yc.dao.DiaryDao;
import com.yc.dao.UserDao;
import dev.langchain4j.data.message.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Instant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class UserDailyAnalysisService {
    
    private static final Logger logger = LoggerFactory.getLogger(UserDailyAnalysisService.class);
    
    // Redis键前缀
    private static final String DAILY_ANALYSIS_PREFIX = "daily:analysis:";
    private static final String PSYCHOLOGY_ANALYSIS_PREFIX = "chat:Psychlogy:";
    
    // 数据过期时间（天）
    private static final long EXPIRE_DAYS = 90;
    
    @Autowired
    private UserDao userDao;
    
    @Autowired
    private DiaryDao diaryDao;
    
    @Autowired
    private PersistentMemoryStore memoryStore;
    
    @Autowired
    private PsychologyAnalysisService psychologyAnalysisService;
    
    @Autowired
    private AiConfig.AiAssistant aiAssistant;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private DailyAnalysisProperties dailyAnalysisProperties;
    
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    /**
     * 每天凌晨1点执行用户心理状态分析
     */
    @Scheduled(cron = "${psychology.daily-analysis.cron:0 0 1 * * ?}")
    public void performDailyAnalysis() {
        if (!dailyAnalysisProperties.isEnabled()) {
            logger.info("每日心理分析任务已禁用，跳过执行");
            return;
        }
        logger.info("开始执行每日用户心理状态分析任务");
        
        try {
            // 获取所有用户
            List<User> allUsers = userDao.selectList(null);
            
            if (allUsers == null || allUsers.isEmpty()) {
                logger.info("没有找到用户，跳过分析任务");
                return;
            }
            
            LocalDate yesterday = LocalDate.now().minusDays(1);
            String dateStr = yesterday.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            
            logger.info("开始分析 {} 的用户数据，共 {} 个用户", dateStr, allUsers.size());
            
            int successCount = 0;
            int skipCount = 0;
            
            for (User user : allUsers) {
                try {
                    String userId = user.getUserId().toString();
                    
                    // 收集用户昨天的数据
                    Map<String, Object> userData = collectUserDailyData(userId, yesterday);
                    
                    if (userData.isEmpty()) {
                        logger.debug("用户 {} 在 {} 没有活动数据，跳过分析", userId, dateStr);
                        skipCount++;
                        continue;
                    }
                    
                    // 调用AI进行分析
                    String analysisResult = performAIAnalysis(userId, userData, dateStr);
                    
                    if (analysisResult != null && !analysisResult.isEmpty()) {
                        // 存储分析结果
                        saveDailyAnalysis(userId, yesterday, analysisResult, userData);
                        successCount++;
                        logger.info("用户 {} 的 {} 心理分析完成", userId, dateStr);
                    } else {
                        logger.warn("用户 {} 的 {} 心理分析失败：AI返回空结果", userId, dateStr);
                    }
                    
                    // 添加延迟避免API调用过于频繁
                    Thread.sleep(dailyAnalysisProperties.getApiCallInterval());
                    
                } catch (Exception e) {
                    logger.error("分析用户 {} 的 {} 数据时发生错误", user.getUserId(), dateStr, e);
                }
            }
            
            logger.info("每日心理分析任务完成。成功: {}, 跳过: {}, 总计: {}", 
                    successCount, skipCount, allUsers.size());
            
        } catch (Exception e) {
            logger.error("执行每日心理分析任务时发生错误", e);
        }
    }
    
    /**
     * 收集用户指定日期的数据
     */
    private Map<String, Object> collectUserDailyData(String userId, LocalDate targetDate) {
        Map<String, Object> userData = new HashMap<>();
        
        try {
            // 1. 收集聊天记录
            Map<String, Object> chatData = collectChatData(userId, targetDate);
            if (!chatData.isEmpty()) {
                userData.put("chatRecords", chatData);
            }
            
            // 2. 收集心理分析记录（图片分析）
            List<Map<String, Object>> psychologyData = collectPsychologyAnalysisData(userId, targetDate);
            if (!psychologyData.isEmpty()) {
                userData.put("psychologyAnalysis", psychologyData);
            }
            
            // 3. 收集日记记录
            List<Map<String, Object>> diaryData = collectDiaryData(userId, targetDate);
            if (!diaryData.isEmpty()) {
                userData.put("diaries", diaryData);
            }
            
            int chatCount = chatData.size();
            int psychologyCount = psychologyData.size();
            int diaryCount = diaryData.size();
            
            logger.info("用户 {} 在 {} 的数据收集完成：聊天记录 {} 个角色, 心理分析 {} 条, 日记 {} 条", 
                    userId, targetDate, chatCount, psychologyCount, diaryCount);
            
        } catch (Exception e) {
            logger.error("收集用户 {} 在 {} 的数据时发生错误", userId, targetDate, e);
        }
        
        return userData;
    }
    
    /**
     * 收集聊天记录数据
     */
    private Map<String, Object> collectChatData(String userId, LocalDate targetDate) {
        Map<String, Object> chatData = new HashMap<>();
        
        try {
            // 获取用户的聊天记录（三角色模式）
            Set<String> allKeys = memoryStore.getKeysByPattern(userId + "_*");
            Set<String> targetKeywords = Set.of("listener", "coach", "mentor", "patient");
            
            // 转换为毫秒级时间戳进行比较
            long targetTimestamp = targetDate.atStartOfDay().toInstant(java.time.ZoneOffset.of("+8")).toEpochMilli();
            long nextDayTimestamp = targetDate.plusDays(1).atStartOfDay().toInstant(java.time.ZoneOffset.of("+8")).toEpochMilli();
            
            logger.debug("收集用户 {} 在 {} 的聊天数据，时间范围：{} - {}", 
                    userId, targetDate, targetTimestamp, nextDayTimestamp);
            
            for (String key : allKeys) {
                String[] parts = key.split("_");
                if (parts.length >= 3) {
                    try {
                        long keyTimestamp = Long.parseLong(parts[1]);
                        String role = parts[2];
                        
                        logger.debug("检查键：{}，时间戳：{}（{}），角色：{}", 
                                key, keyTimestamp, timestampToDateString(keyTimestamp), role);
                        
                        // 检查时间戳是否在目标日期范围内
                        if (keyTimestamp >= targetTimestamp && keyTimestamp < nextDayTimestamp 
                            && targetKeywords.contains(role)) {
                            
                            List<ChatMessage> messages = memoryStore.getMessages(key);
                            List<Map<String, Object>> roleMessages = new ArrayList<>();
                            
                            for (ChatMessage msg : messages) {
                                if (msg.type() != ChatMessageType.SYSTEM) {
                                    Map<String, Object> messageObj = new HashMap<>();
                                    messageObj.put("type", msg.type().toString());
                                    messageObj.put("content", extractMessageContent(msg));
                                    messageObj.put("timestamp", keyTimestamp);
                                    roleMessages.add(messageObj);
                                }
                            }
                            
                            if (!roleMessages.isEmpty()) {
                                chatData.put(role, roleMessages);
                                logger.debug("添加角色 {} 的消息，数量：{}", role, roleMessages.size());
                            }
                        } else {
                            logger.debug("键 {} 不在时间范围内或角色不匹配", key);
                        }
                    } catch (NumberFormatException e) {
                        logger.debug("解析时间戳失败，键: {}", key);
                    }
                }
            }
            
        } catch (Exception e) {
            logger.error("收集用户 {} 聊天数据时发生错误", userId, e);
        }
        
        return chatData;
    }
    
    /**
     * 收集心理分析数据（图片分析）
     */
    private List<Map<String, Object>> collectPsychologyAnalysisData(String userId, LocalDate targetDate) {
        List<Map<String, Object>> analysisData = new ArrayList<>();
        
        try {
            // 构建Redis key模式
            String pattern = PSYCHOLOGY_ANALYSIS_PREFIX + userId + "_*";
            Set<String> keys = redisTemplate.keys(pattern);
            
            if (keys != null && !keys.isEmpty()) {
                // 转换为毫秒级时间戳进行比较
                long targetTimestamp = targetDate.atStartOfDay().toInstant(java.time.ZoneOffset.of("+8")).toEpochMilli();
                long nextDayTimestamp = targetDate.plusDays(1).atStartOfDay().toInstant(java.time.ZoneOffset.of("+8")).toEpochMilli();
                
                logger.debug("收集用户 {} 在 {} 的心理分析数据，时间范围：{} - {}", 
                        userId, targetDate, targetTimestamp, nextDayTimestamp);
                
                for (String key : keys) {
                    try {
                        String[] keyParts = key.split("_");
                        if (keyParts.length >= 2) {
                            long keyTimestamp = Long.parseLong(keyParts[keyParts.length - 1]);
                            
                            logger.debug("检查心理分析键：{}，时间戳：{}（{}）", 
                                    key, keyTimestamp, timestampToDateString(keyTimestamp));
                            
                            // 检查时间戳是否在目标日期范围内
                            if (keyTimestamp >= targetTimestamp && keyTimestamp < nextDayTimestamp) {
                                Object value = redisTemplate.opsForValue().get(key);
                                if (value != null) {
                                    Map<String, Object> analysis = objectMapper.readValue(value.toString(), Map.class);
                                    analysis.put("timestamp", keyTimestamp);
                                    analysisData.add(analysis);
                                    logger.debug("添加心理分析数据，键：{}", key);
                                }
                            } else {
                                logger.debug("心理分析键 {} 不在时间范围内", key);
                            }
                        }
                    } catch (Exception e) {
                        logger.debug("解析心理分析数据失败，键: {}, 错误: {}", key, e.getMessage());
                    }
                }
            }
            
        } catch (Exception e) {
            logger.error("收集用户 {} 心理分析数据时发生错误", userId, e);
        }
        
        return analysisData;
    }
    
    /**
     * 收集日记数据
     */
    private List<Map<String, Object>> collectDiaryData(String userId, LocalDate targetDate) {
        List<Map<String, Object>> diaryData = new ArrayList<>();
        
        try {
            LocalDateTime startTime = targetDate.atStartOfDay();
            LocalDateTime endTime = targetDate.plusDays(1).atStartOfDay();
            
            QueryWrapper<Diary> wrapper = new QueryWrapper<>();
            wrapper.eq("userId", Long.parseLong(userId))
                    .eq("status", 1)
                    .between("createTime", startTime, endTime)
                    .orderByAsc("createTime");
            
            List<Diary> diaries = diaryDao.selectList(wrapper);
            
            for (Diary diary : diaries) {
                Map<String, Object> diaryObj = new HashMap<>();
                diaryObj.put("title", diary.getTitle());
                diaryObj.put("content", diary.getContent());
                diaryObj.put("createTime", diary.getCreateTime().toString());
                diaryData.add(diaryObj);
            }
            
        } catch (Exception e) {
            logger.error("收集用户 {} 日记数据时发生错误", userId, e);
        }
        
        return diaryData;
    }
    
    /**
     * 调用AI进行心理分析
     */
    private String performAIAnalysis(String userId, Map<String, Object> userData, String dateStr) {
        try {
            // 构建分析请求内容
            StringBuilder analysisRequest = new StringBuilder();
            analysisRequest.append("用户ID: ").append(userId).append("\n");
            analysisRequest.append("分析日期: ").append(dateStr).append("\n\n");
            
            // 添加聊天记录
            if (userData.containsKey("chatRecords")) {
                analysisRequest.append("=== 聊天记录 ===\n");
                Map<String, Object> chatData = (Map<String, Object>) userData.get("chatRecords");
                for (Map.Entry<String, Object> entry : chatData.entrySet()) {
                    analysisRequest.append("角色: ").append(entry.getKey()).append("\n");
                    List<Map<String, Object>> messages = (List<Map<String, Object>>) entry.getValue();
                    for (Map<String, Object> msg : messages) {
                        analysisRequest.append("- [").append(msg.get("type")).append("] ")
                                      .append(msg.get("content")).append("\n");
                    }
                    analysisRequest.append("\n");
                }
            }
            
            // 添加心理分析记录
            if (userData.containsKey("psychologyAnalysis")) {
                analysisRequest.append("=== 图片心理分析记录 ===\n");
                List<Map<String, Object>> analyses = (List<Map<String, Object>>) userData.get("psychologyAnalysis");
                for (Map<String, Object> analysis : analyses) {
                    analysisRequest.append("分析内容: ").append(analysis.get("analysisText")).append("\n");
                    analysisRequest.append("图片URL: ").append(analysis.get("imageUrl")).append("\n\n");
                }
            }
            
            // 添加日记记录
            if (userData.containsKey("diaries")) {
                analysisRequest.append("=== 日记记录 ===\n");
                List<Map<String, Object>> diaries = (List<Map<String, Object>>) userData.get("diaries");
                for (Map<String, Object> diary : diaries) {
                    analysisRequest.append("标题: ").append(diary.get("title")).append("\n");
                    analysisRequest.append("内容: ").append(diary.get("content")).append("\n");
                    analysisRequest.append("心情: ").append(diary.get("mood")).append("\n");
                    analysisRequest.append("天气: ").append(diary.get("weather")).append("\n\n");
                }
            }
            
            // 调用AI分析
            String memoryId = userId + "_daily_analysis";
            String result = aiAssistant.analyzeUserHistory(memoryId, analysisRequest.toString());
            
            logger.debug("用户 {} 的AI分析请求内容长度: {}", userId, analysisRequest.length());
            
            return result;
            
        } catch (Exception e) {
            logger.error("为用户 {} 执行AI分析时发生错误", userId, e);
            return null;
        }
    }
    
    /**
     * 保存每日分析结果
     */
    private void saveDailyAnalysis(String userId, LocalDate date, String analysisResult, Map<String, Object> userData) {
        try {
            long timestamp = date.atStartOfDay().toEpochSecond(java.time.ZoneOffset.of("+8"));
            String redisKey = DAILY_ANALYSIS_PREFIX + userId + "_" + timestamp;
            
            Map<String, Object> analysisData = new HashMap<>();
            analysisData.put("userId", userId);
            analysisData.put("analysisDate", date.toString());
            analysisData.put("analysisResult", analysisResult);
            analysisData.put("dataCount", calculateDataCount(userData));
            analysisData.put("createTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            analysisData.put("timestamp", timestamp);
            
            String jsonData = objectMapper.writeValueAsString(analysisData);
            redisTemplate.opsForValue().set(redisKey, jsonData, dailyAnalysisProperties.getDataRetentionDays(), TimeUnit.DAYS);
            
            logger.info("用户 {} 的 {} 每日心理分析结果已保存到Redis", userId, date);
            
        } catch (JsonProcessingException e) {
            logger.error("序列化用户 {} 的每日分析数据失败", userId, e);
        } catch (Exception e) {
            logger.error("保存用户 {} 的每日分析结果失败", userId, e);
        }
    }
    
    /**
     * 计算数据统计
     */
    private Map<String, Integer> calculateDataCount(Map<String, Object> userData) {
        Map<String, Integer> dataCount = new HashMap<>();
        
        // 统计聊天记录数量
        if (userData.containsKey("chatRecords")) {
            Map<String, Object> chatData = (Map<String, Object>) userData.get("chatRecords");
            int totalChatMessages = 0;
            for (Object messages : chatData.values()) {
                totalChatMessages += ((List<?>) messages).size();
            }
            dataCount.put("chatMessages", totalChatMessages);
            dataCount.put("chatRoles", chatData.size());
        } else {
            dataCount.put("chatMessages", 0);
            dataCount.put("chatRoles", 0);
        }
        
        // 统计心理分析数量
        if (userData.containsKey("psychologyAnalysis")) {
            List<?> analyses = (List<?>) userData.get("psychologyAnalysis");
            dataCount.put("psychologyAnalyses", analyses.size());
        } else {
            dataCount.put("psychologyAnalyses", 0);
        }
        
        // 统计日记数量
        if (userData.containsKey("diaries")) {
            List<?> diaries = (List<?>) userData.get("diaries");
            dataCount.put("diaries", diaries.size());
        } else {
            dataCount.put("diaries", 0);
        }
        
        return dataCount;
    }
    
    /**
     * 将毫秒时间戳转换为日期字符串（用于调试）
     */
    private String timestampToDateString(long timestamp) {
        try {
            LocalDateTime dateTime = LocalDateTime.ofInstant(
                Instant.ofEpochMilli(timestamp), 
                java.time.ZoneOffset.of("+8")
            );
            return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        } catch (Exception e) {
            return "无效时间戳: " + timestamp;
        }
    }
    
    /**
     * 提取消息内容
     */
    private String extractMessageContent(ChatMessage msg) {
        switch (msg.type()) {
            case SYSTEM:
                return ((SystemMessage) msg).text();
            case USER:
                UserMessage userMessage = (UserMessage) msg;
                // 优先使用 singleText() 方法（当只有单个文本内容时）
                if (userMessage.hasSingleText()) {
                    return userMessage.singleText();
                }
                // 如果有多个内容，返回字符串表示
                return userMessage.toString();
            case AI:
                return ((AiMessage) msg).text();
            default:
                return msg.toString();
        }
    }
    
    /**
     * 获取用户的每日分析历史
     */
    public String getUserDailyAnalysisHistory(String userId) {
        try {
            String pattern = DAILY_ANALYSIS_PREFIX + userId + "_*";
            Set<String> keys = redisTemplate.keys(pattern);
            
            if (keys == null || keys.isEmpty()) {
                logger.info("用户 {} 没有每日分析历史记录", userId);
                return null;
            }
            
            List<Object> values = redisTemplate.opsForValue().multiGet(keys);
            List<Map<String, Object>> historyList = new ArrayList<>();
            
            for (int i = 0; i < keys.size(); i++) {
                Object value = values.get(i);
                if (value != null) {
                    try {
                        Map<String, Object> analysisData = objectMapper.readValue(value.toString(), Map.class);
                        historyList.add(analysisData);
                    } catch (Exception e) {
                        logger.warn("解析每日分析历史记录失败", e);
                    }
                }
            }
            
            if (historyList.isEmpty()) {
                return null;
            }
            
            // 按时间戳降序排序
            historyList.sort((a, b) -> {
                try {
                    Long timestampA = Long.parseLong(a.get("timestamp").toString());
                    Long timestampB = Long.parseLong(b.get("timestamp").toString());
                    return Long.compare(timestampB, timestampA);
                } catch (Exception e) {
                    return 0;
                }
            });
            
            return objectMapper.writeValueAsString(historyList);
            
        } catch (Exception e) {
            logger.error("获取用户 {} 的每日分析历史失败", userId, e);
            return null;
        }
    }
    
    /**
     * 手动触发指定用户的分析任务（用于测试）
     */
    public boolean triggerAnalysisForUser(String userId, LocalDate targetDate) {
        try {
            logger.info("手动触发用户 {} 在 {} 的心理分析", userId, targetDate);
            
            Map<String, Object> userData = collectUserDailyData(userId, targetDate);
            
            if (userData.isEmpty()) {
                logger.info("用户 {} 在 {} 没有活动数据", userId, targetDate);
                return false;
            }
            
            String analysisResult = performAIAnalysis(userId, userData, targetDate.toString());
            
            if (analysisResult != null && !analysisResult.isEmpty()) {
                saveDailyAnalysis(userId, targetDate, analysisResult, userData);
                logger.info("用户 {} 的 {} 心理分析手动触发完成", userId, targetDate);
                return true;
            } else {
                logger.warn("用户 {} 的 {} 心理分析失败：AI返回空结果", userId, targetDate);
                return false;
            }
            
        } catch (Exception e) {
            logger.error("手动触发用户 {} 的心理分析失败", userId, e);
            return false;
        }
    }
} 